/*
***************************************************************************************************
*   AD7682.c
*   AD7682 驱动文件，仅使用了内部参考4.096V电压模式，提供了函数读取4个通道的电压值。
*
***************************************************************************************************
*/

#include "main.h"   // 提供引脚宏定义
#include "AD7682.h" // 提供CFG寄存器结构定义

#include "usb_task.h"

static
void naive_delay_us(uint16_t nus)
{
    uint32_t i,j;
    uint8_t nothing;
    nothing  = 0;
    for(i = 0; i < nus; i++)
    {
        for(j = 0; j < ((uint32_t)(1)); j++)
        {
                nothing ++ ;
        }
    }
}

static inline
void reset_sck(void)
{
    HAL_GPIO_WritePin(HAND_AD7682_SCK_GPIO_Port,HAND_AD7682_SCK_Pin,GPIO_PIN_RESET);
}

static inline
void set_sck(void)
{
    HAL_GPIO_WritePin(HAND_AD7682_SCK_GPIO_Port,HAND_AD7682_SCK_Pin,GPIO_PIN_SET);
}

static inline
void set_cs(void)
{
    HAL_GPIO_WritePin(HAND_AD7682_CS_GPIO_Port,HAND_AD7682_CS_Pin,GPIO_PIN_SET);
}

static inline
void reset_cs(void)
{
    HAL_GPIO_WritePin(HAND_AD7682_CS_GPIO_Port,HAND_AD7682_CS_Pin,GPIO_PIN_RESET);
}

static inline
void delay_moment(void)
{
    // naive_delay_us(20);
    HAL_Delay(1);
    
}

static inline
void delay_shorter_moment(void)
{
    naive_delay_us(2);
}

static inline
void write_MOSI(uint16_t signal)
{
    HAL_GPIO_WritePin(HAND_AD7682_MOSI_GPIO_Port,HAND_AD7682_MOSI_Pin,(GPIO_PinState)(signal));
}

static inline
uint16_t read_MISO(void)
{
    return (uint16_t) (HAL_GPIO_ReadPin(HAND_AD7682_MISO_GPIO_Port,HAND_AD7682_MISO_Pin));
}


static uint8_t AD7682_overflow_flag = 0;    // 溢出标志
static uint16_t rec_data;                          // 获取到的数据

static AD7682_config_s cfg_info = {
        1,  // 不回读
        0,  // 禁用序列器
        1,  // 内部基准电压，REF = 4.096
        1,  // 全带宽
        0,  // 通道0
        7,  // 单极性，以GND为参考
        1   // 配置更新：覆盖寄存器内容
    };

/****************************************************************************
函数名	： read_AD7682_voltage
功能	： 从AD7682一个端口的读取电压值
参数	： channel - 通道号码，取值为0,1,2,3
返回值	： voltage 读取到的电压，取值为0~4.096V
****************************************************************************/
float read_AD7682_voltage (uint8_t channel)
{
    uint16_t cfg_buf;
    uint8_t i,j;
    float voltage;

    for(j = 0; j < 10 ; j++)    //读10次到达稳定，避免初始的错乱数据的影响
    {
        // 初始化时钟信号，静止状态为低电平
        reset_sck();

        // 拉高cs，启动转换
        reset_cs();
        set_cs();
        delay_moment();
        reset_cs();
        delay_shorter_moment();

        // 初始化，准备发送数据和接收数据
        rec_data = 0;

        // 判定通道号只有在此范围：0-3内的才能发送
        if(channel < 4)
            cfg_info.channel_index = channel;
        cfg_buf = *((uint16_t * )(&cfg_info)) << 2; // cfg只有14位，要在前14个周期内完全发送，因此在低位补两个0
        for(i = 0;i<16;i++)
        {
            write_MOSI((cfg_buf>>(15-i))&0x1);
            delay_shorter_moment();
            set_sck();
            delay_shorter_moment();
            rec_data <<=1;
            rec_data |= read_MISO();
            reset_sck();
            delay_shorter_moment();
        }
    }

    AD7682_overflow_flag = (rec_data == 0xffff) ? 1 : 0;
    voltage = ((double)rec_data) * (4.096) / 0xffff;
    return voltage;
}

/****************************************************************************
函数名	： get_AD7682_overflow
功能	： 判定AD7682上一次读取电压时是否溢出
参数	： 无
返回值	： AD7682_overflow_flag - 为1时表示溢出了，为0时表示没有溢出
****************************************************************************/
uint8_t get_AD7682_overflow(void)
{
    return AD7682_overflow_flag;
}
